package model.icmpv6;

import header.ICMPv6Defines;

import java.util.ArrayList;
import java.util.List;

public abstract class ICMPv6Packet {
	protected int type;
	protected int code;
	protected int checksum[];
	protected int reserved[];
	protected List<ICMPv6Option> options;
	
	public ICMPv6Packet() {
		options = new ArrayList<>();
	}

	public ICMPv6Packet(int type, int code,
			List<ICMPv6Option> options) {
		this.type = type;
		this.code = code;
		this.options = options;
		this.reserved = new int[4];
		this.checksum = new int[2];
	}

	public static long checksum() {
		
	    int[] buf = {0x85, 0x00, 0x6c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x21, 0x00, 0xb4, 0x42, 0x50};
	    int length = buf.length;
	    int i = 0;

	    long sum = 0;
	    long data = 0;
	    while (length > 1) {
	        data = 0;
	        data = (((buf[i]) << 8) | ((buf[i + 1]) & 0xFF));

	        sum += data;
	        if ((sum & 0xFFFF0000) > 0) {
	            sum = sum & 0xFFFF;
	            sum += 1;
	        }

	        i += 2;
	        length -= 2;
	    }

	    if (length > 0) {
	        sum += (buf[i] << 8);
	        // sum += buffer[i];
	        if ((sum & 0xFFFF0000) > 0) {
	            sum = sum & 0xFFFF;
	            sum += 1;
	        }
	    }
	    sum = ~sum;
	    sum = sum & 0xFFFF;
	    return sum;
	}

	
	public void addOption(ICMPv6Option opt){
		this.options.add(opt);
	}
	
	public List<Integer> makePacket(){
		List<Integer> retList = new ArrayList<Integer>();
		retList.add(type);
		retList.add(code);
		/* add checksum */
		for(int chksum : checksum){
			retList.add(chksum);
		}
		
		/* add reserved */
		for(int res : reserved){
			retList.add(res);
		}
		
		/* add options */
		for(ICMPv6Option opt : options){
			retList.addAll(opt.makeOption());
		}
		return retList;
	}
}
